#include "thread_spider.h"

#define kDestoryTimeMS (30 * 60 * 1000)

WKRequest::WKRequest(std::string url, boost::function< void (WebPage *)> cb, int level)
    : m_url(url)
    , m_level(level)
    , m_alive(true)
{
    m_sig.connect(cb);
}

WKRequest::~WKRequest()
{
}

void WKRequest::start()
{
    boost::function0< void> func = boost::bind(&WKRequest::run ,this);
    boost::thread thrd(func);
    thrd.detach();
}

void WKRequest::run()
{
    WebKit *webkit = NULL;
    WebPage *page = NULL;
    while(1) {
        webkit = new WebKit("test");
        //std::cout << "thread: " << boost::this_thread::get_id() << " get: " << m_url << std::endl;
        page = webkit->getWebPage(m_url, m_level, kDestoryTimeMS);
        if (page != NULL) {
            break;
        } else {
            std::cout << "thread: " << boost::this_thread::get_id() << " get failed : " << m_url << std::endl;
            delete webkit;
            sleep(1);
        }
    }
    std::cout << "thread: " << boost::this_thread::get_id() << " get success : " << m_url << std::endl;
    usleep(200000);
    //std::cout << "thread: " << boost::this_thread::get_id() << " get: " << page->getUrl() << " title: " << page->getTitle() << std::endl;
    m_sig(page);
    webkit->destoryWebPage(page);
    std::cout << "thread: " << boost::this_thread::get_id() << " died." << std::endl;
    m_alive = false;
    delete webkit;
}

bool WKRequest::isAlive()
{
    return m_alive;
}

void ThreadSpider::destroyRequest(WKRequest* request)
{
    boost::mutex::scoped_lock lock(m_requestMutex);
    if (request)
        delete request;
}

void ThreadSpider::start()
{
    boost::function0< void> func = boost::bind(&ThreadSpider::run ,this);
    boost::thread thrd(func);
    thrd.detach();
}

void ThreadSpider::run()
{
    while(1) {
        usleep(100000);

        std::list<WKRequest*>::iterator it;
        for (it = m_aliveRequests.begin(); it != m_aliveRequests.end(); it ++) {
            if (!(*it)->isAlive()) {
                m_diedRequests.push_back(*it);
            }
        }

        if(m_diedRequests.size() > 0) {
            std::list<WKRequest*>::iterator it;
            for (it = m_diedRequests.begin(); it != m_diedRequests.end(); it ++) {
                m_aliveRequests.remove(*it);
                destroyRequest((*it));
            }
            m_diedRequests.clear();
        }

        if (m_requests.size() <= 0)
            continue;

        if(m_aliveRequests.size() >= LIMIT_CONNECT_SIZE)
            continue;

        int ssize = 0;

        if ((LIMIT_CONNECT_SIZE - m_aliveRequests.size()) < m_requests.size())
            ssize = LIMIT_CONNECT_SIZE - m_aliveRequests.size();
        else
            ssize = m_requests.size();

        for(int i = 0; i < ssize; i ++) {
            WKRequest *req = m_requests.front();
            m_requests.pop_front();
            m_aliveRequests.push_back(req);
            req->start();
        }

        printf("[ThreadSpider] wait: %d alive: %d\n", m_requests.size(), m_aliveRequests.size());
    }
}

long ThreadSpider::requestCount()
{
    return m_requests.size() + m_aliveRequests.size();
}

